package com.bjh.config;

import cn.hutool.json.JSONUtil;
import com.bjh.annotation.Service;
import com.bjh.components.ZookUtil;
import com.bjh.model.InterfaceImplInfo;
import com.bjh.model.InterfaceInfo;
import com.bjh.model.ZkNodeData;
import com.bjh.model.ZkProperties;
import com.bjh.util.ClassUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Slf4j
@Configuration
public class ProcessServiceAnnotationConfig implements InitializingBean {


    ObjectMapper objectMapper = new ObjectMapper();

    private static final String REGISTER_PATH = "/rpc";

    @Resource
    private ZkPropertiesSource zkPropertiesSource;

    @Resource
    private ZookUtil zookUtil;

    @Resource
    private Environment environment;

    @Override
    public void afterPropertiesSet() throws Exception {
        String packageName = zkPropertiesSource.getPackageName();
        log.info("packageName = {}",packageName);
        Set<Class<?>> classes = ClassUtil.extractPackageClass(packageName);

        for(Class clazz : classes) {

            String clazzName = clazz.getName();
            log.info("className = {}",clazzName);
            //如果这个class是个接口就不做处理
            if(clazzName.contains("$") || clazz.isInterface()) {
                continue;
            }
            if(clazz.isAnnotationPresent(Service.class)) {
                //说明该类上有我们自定义的注解，然后拿到实现的接口
                Class[] interfaces = clazz.getInterfaces();
                //首先判断该节点是否已经注册到zk上了
                for(Class interfaceClazz : interfaces) {
                    String nodeData = zookUtil.getNodeData(REGISTER_PATH);
                    log.info("nodeData = {}",nodeData);
                    if(StringUtils.isEmpty(nodeData)) {
                        ZkNodeData zkNodeData = new ZkNodeData();
                        List<ZkProperties> zkPropertiesList = new ArrayList<>();
                        //说明该接口之前已经被注册过了
                        ZkProperties zkProperties = new ZkProperties();
                        zkProperties.setInterfaceName(interfaceClazz.getName());
                        List<InterfaceInfo> info = new ArrayList<>();
                        InterfaceInfo interfaceInfo = new InterfaceInfo();
                        //拿到当前主机的ip地址
                        InetAddress localHost = InetAddress.getLocalHost();
                        interfaceInfo.setIpAddress(localHost.getHostAddress() + ":" + zkPropertiesSource.getNettyServerPort());
                        List<InterfaceImplInfo> interfaceImplInfos = new ArrayList<>();
                        InterfaceImplInfo interfaceImplInfo = new InterfaceImplInfo();
                        interfaceImplInfo.setName(clazz.getName());
                        interfaceImplInfo.setValue(clazz.getName());
                        interfaceImplInfos.add(interfaceImplInfo);
                        interfaceInfo.setInterfaceImplInfo(interfaceImplInfos);
                        info.add(interfaceInfo);
                        zkProperties.setInfo(info);
                        zkPropertiesList.add(zkProperties);
                        zkNodeData.setZkPropertiesList(zkPropertiesList);
                        String body = objectMapper.writeValueAsString(zkNodeData);
                        log.info("if - 节点数据是：{}",body);
                        zookUtil.createNode(REGISTER_PATH,body);
                    }
                    else {
                        ZkNodeData zkNodeData = objectMapper.readValue(nodeData, ZkNodeData.class);
                        log.info("ZkNodeData = {}", JSONUtil.toJsonPrettyStr(zkNodeData));
                        List<ZkProperties> zkPropertiesListNew = new ArrayList<>();
                        List<ZkProperties> properties = zkNodeData.getZkPropertiesList();
                        zkPropertiesListNew.addAll(properties);
                        if(properties != null && !properties.isEmpty()) {
                            for(ZkProperties zkProperties : properties) {
                                if(StringUtils.equals(interfaceClazz.getName(),zkProperties.getInterfaceName())) {
                                    List<InterfaceInfo> info = zkProperties.getInfo();
                                    for(InterfaceInfo interfaceInfo : info) {
                                        String ipAddress = InetAddress.getLocalHost().getHostAddress() + ":" + zkPropertiesSource.getNettyServerPort();
                                        if(StringUtils.equals(ipAddress,interfaceInfo.getIpAddress())) {
                                            List<InterfaceImplInfo> interfaceImplInfo = interfaceInfo.getInterfaceImplInfo();
                                            boolean isExist = false;
                                            for(InterfaceImplInfo interfaceImplInfo1 : interfaceImplInfo) {
                                                String name = interfaceImplInfo1.getName();
                                                if(StringUtils.equals(name,clazz.getName())) {
                                                    isExist = true;
                                                }
                                            }

                                            if(!isExist) {
                                                InterfaceImplInfo implInfo = new InterfaceImplInfo();
                                                implInfo.setName(clazz.getName());
                                                implInfo.setValue(clazz.getName());
                                                interfaceImplInfo.add(implInfo);
                                            }
                                        }
                                    }
                                }else {
                                    ZkProperties zkPropertiesToSave = new ZkProperties();
                                    zkPropertiesToSave.setInterfaceName(interfaceClazz.getName());
                                    List<InterfaceInfo> info = new ArrayList<>();
                                    InterfaceInfo interfaceInfo = new InterfaceInfo();
                                    //拿到当前主机的ip地址
                                    InetAddress localHost = InetAddress.getLocalHost();
                                    interfaceInfo.setIpAddress(localHost.getHostAddress() + ":" + zkPropertiesSource.getNettyServerPort());
                                    List<InterfaceImplInfo> interfaceImplInfos = new ArrayList<>();
                                    InterfaceImplInfo interfaceImplInfo = new InterfaceImplInfo();
                                    interfaceImplInfo.setName(clazz.getName());
                                    interfaceImplInfo.setValue(clazz.getName());
                                    interfaceImplInfos.add(interfaceImplInfo);
                                    interfaceInfo.setInterfaceImplInfo(interfaceImplInfos);
                                    info.add(interfaceInfo);
                                    zkPropertiesToSave.setInfo(info);
                                    zkPropertiesListNew.add(zkPropertiesToSave);
                                }
                            }
                            zkNodeData.setZkPropertiesList(zkPropertiesListNew);
                            String body = objectMapper.writeValueAsString(zkNodeData);
                            log.info("else - 节点数据是：{}",body);
                            zookUtil.updateData(REGISTER_PATH,body);
                        }

                    }
                }

            }
        }
    }
}
